
package com.hlkj.pay.app.merchant.ext.impl.leshua.handler;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.Charset;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.HttpEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.hlkj.framework.caches.service.RedisTemplateService;
import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.util.id.IdUtils;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.pay.app.common.impl.UploadServiceImpl;
import com.hlkj.pay.app.merchant.ext.impl.leshua.constant.HttpClientHelper;
import com.hlkj.pay.app.merchant.ext.impl.leshua.constant.LeshuaPayConstant;
import com.hlkj.pay.app.merchant.ext.impl.leshua.constant.XmlUtils;
import com.hlkj.pay.app.merchant.ext.impl.leshua.dto.LeshuaPayConfig;
import com.hlkj.pay.app.merchant.ext.impl.leshua.dto.resp.*;
import com.hlkj.pay.app.merchant.ext.impl.yeepay.dto.YeePayDivideDetailResp;
import com.hlkj.pay.common.PayResultCode;
import com.hlkj.pay.dto.merchant.MerchantAccessScene;
import com.hlkj.pay.dto.merchant.ProviderChannelFeeConfigList;
import com.hlkj.pay.dto.provider.StepFeeConfig;
import com.hlkj.pay.enums.MerchantEnum;
import com.hlkj.pay.enums.PayEnums;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAccessInfoDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantConfigDO;
import com.hlkj.pay.infrastructure.model.order.PayOrderDO;
import com.hlkj.pay.infrastructure.model.pay.PayChannelRequestDO;
import com.hlkj.pay.infrastructure.model.pay.PayWayDO;
import com.hlkj.pay.infrastructure.model.pay.ProviderChannelConfigDO;
import com.hlkj.pay.service.merchant.IMerchantConfigService;
import com.hlkj.pay.service.order.IPayOrderService;
import com.hlkj.pay.service.pay.IPayChannelService;
import com.hlkj.pay.service.pay.IPayWayService;
import com.hlkj.pay.util.ImageUtils;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.XmlUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 乐刷服务商 商户进件参数处理
 * 
 * @author HlpayTeam
 * @date 2024/09/26 12:02
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class LeshuaPayCommonParamsHandle {

    private final UploadServiceImpl uploadService;

    private final RedisTemplateService redisTemplateService;

    private final IPayOrderService payOrderService;

    private final IPayWayService payWayService;

    private final IMerchantConfigService merchantConfigService;

    private final IPayChannelService payChannelService;

    static HttpClientHelper httpClientHelper = new HttpClientHelper();


    public void updateFeeInfo(MerchantAccessInfoDO merchantAccessInfoDO,LeshuaPayConfig leshuaPayConfig){
        try{
            log.info("乐刷收单费率设置 开始");
            // 判断是否已经请求过
            PayChannelRequestDO oldRequest = payChannelService.queryRequestByAccessId(merchantAccessInfoDO.getRequestId(),LeshuaPayConstant.OPEN_URL);
            log.info("乐刷收单费率设置 查询：{}",oldRequest);
            if(oldRequest != null){
                log.info("乐刷收单费率设置 已存在:{}", JsonUtils.toJsonString(oldRequest));
                return;
            }
            // 获取商户费率配置
            MerchantConfigDO merchantConfigDO = merchantConfigService.queryConfig(merchantAccessInfoDO.getSn());
            List<ProviderChannelFeeConfigList> merchantFeeConfigList = merchantConfigDO.getMerchantFeeConfigList();
            merchantFeeConfigList.stream().forEach(merchantConfig -> {
                merchantConfig.setPayWayDO(payWayService.queryByCode(merchantConfig.getPayWayCode()));
            });
            merchantFeeConfigList = merchantFeeConfigList.stream().filter(merchantFeeConfig -> merchantFeeConfig.getPayWayDO() != null).collect(Collectors.toList());
            log.info("乐刷收单费率设置 费率配置：{}",JsonUtils.toJsonString(merchantFeeConfigList));
            // 产品费率组装
            Map<String,Object> productFeeMap = getProductFeeInfo(merchantFeeConfigList);
            productFeeMap.put("merchantId",merchantAccessInfoDO.getSubMchId());

            String reqNo = merchantAccessInfoDO.getRequestId();

            // 保存记录
            PayChannelRequestDO requestDO = new PayChannelRequestDO();
            requestDO.setRequestParams(JsonUtils.toJsonString(productFeeMap));
            requestDO.setSn(merchantAccessInfoDO.getSn());
            requestDO.setProviderCode(merchantAccessInfoDO.getProviderCode());
            requestDO.setChannelCode(merchantAccessInfoDO.getChannelCode());
            requestDO.setRelationId(merchantAccessInfoDO.getRequestId());
            requestDO.setRequestId(reqNo);
            requestDO.setRequestUrl(LeshuaPayConstant.OPEN_URL);

            log.info("乐刷收单费率设置 请求参数 request:{}", JsonUtils.toJsonString(productFeeMap));
            LeshuaBaseResp response = requestPostApi(LeshuaPayConstant.OPEN_URL,JSONUtil.toJsonStr(productFeeMap),leshuaPayConfig,reqNo);
            log.info("乐刷收单费率设置 响应参数 response:{}", JsonUtils.toJsonString(response));

            requestDO.setResponse(JsonUtils.toJsonString(response));
            payChannelService.saveRequest(requestDO,PayEnums.CHANNEL_REQUEST_TYPE.MERCHANT_ACCESS);

            if(response.getRespCode().equals(LeshuaPayConstant.OK)){
                log.info("乐刷收单费率设置 请求成功 response:{}", JsonUtils.toJsonString(response));
            }else{
                log.info("乐刷收单费率设置 请求失败 response:{}", JsonUtils.toJsonString(response));
            }

        }catch (Exception e){
            e.printStackTrace();
            log.error("乐刷收单费率设置 请求失败：{}",e);
        }

    }

    /**
     * 开通产品费率参数组装
     * @param merchantFeeConfigList
     * @return
     */
    public Map<String,Object> getProductFeeInfo(List<ProviderChannelFeeConfigList> merchantFeeConfigList){
        // 费率参数
        Map<String,Object> feedata = new HashMap<>();

        // 微信 t1 offline费率
        Map<String,Object> wx_t1_offline = new HashMap<>();
        wx_t1_offline.put("t1",getRateUnit(merchantFeeConfigList,PayEnums.PAY_TYPE.WECHAT,PayEnums.SCENE_TYPE.OFFLINE,false));
        feedata.put("weixin",wx_t1_offline);

        // 支付宝 t1 offline费率
        Map<String,Object> ali_t1_offline = new HashMap<>();
        ali_t1_offline.put("t1",getRateUnit(merchantFeeConfigList,PayEnums.PAY_TYPE.ALIPAY,PayEnums.SCENE_TYPE.OFFLINE,false));
        feedata.put("alipay",ali_t1_offline);

        // 银联云闪付  <1000 offline费率
        Map<String,Object> unionScan2 = new HashMap<>();
        unionScan2.put("t1Credit",getRateUnit(merchantFeeConfigList,PayEnums.PAY_TYPE.UNION_APY,PayEnums.SCENE_TYPE.OFFLINE,false));
        unionScan2.put("t1Debit",getRateUnit(merchantFeeConfigList,PayEnums.PAY_TYPE.UNION_APY,PayEnums.SCENE_TYPE.OFFLINE,false));
        feedata.put("unionScan2",unionScan2);

        // 银联云闪付 >1000 offline费率
        Map<String,Object> unionScan = new HashMap<>();
        unionScan.put("t1Credit",getRateUnit(merchantFeeConfigList,PayEnums.PAY_TYPE.UNION_APY,PayEnums.SCENE_TYPE.OFFLINE,true));
        unionScan.put("t1Debit",getRateUnit(merchantFeeConfigList,PayEnums.PAY_TYPE.UNION_APY,PayEnums.SCENE_TYPE.OFFLINE,true));
        feedata.put("unionScan",unionScan);

        // 刷卡
        Map<String,Object> card = new HashMap<>();
        // t1 借记卡 0.4-18 单笔无
        Map<String,Object> t1Debit = new HashMap<>();
        t1Debit.put("rate",41);
        t1Debit.put("maxCharge",20*1000000);
        card.put("t1Debit",t1Debit);

        // t1 借记卡 0.42-0 单笔1
        Map<String,Object> t0Debit = new HashMap<>();
        t0Debit.put("rate",51);
        t0Debit.put("maxCharge",0);
        t0Debit.put("fixedCharge",2*1000000);
        card.put("t0Debit",t0Debit);

        // t1 贷记卡 0.51-0 单笔无
        Map<String,Object> t1Credit = new HashMap<>();
        t1Credit.put("rate",52);
        t1Credit.put("maxCharge",0);
        card.put("t1Credit",t1Credit);

        // t0 贷记卡 0.53-0 单笔1
        Map<String,Object> t0Credit = new HashMap<>();
        t0Credit.put("rate",54);
        t0Credit.put("maxCharge",0);
        t0Credit.put("fixedCharge",2*1000000);
        card.put("t0Credit",t0Credit);

        feedata.put("card",card);
        return feedata;
    }
    /**
     * 获取费率信息
     * @param merchantFeeConfigList
     * @param payType
     * @param sceneType
     * @param more1000  是否大于1000
     * @return
     */
    public Map<String,Object> getRateUnit(List<ProviderChannelFeeConfigList> merchantFeeConfigList,PayEnums.PAY_TYPE payType,PayEnums.SCENE_TYPE sceneType, boolean more1000){

        ProviderChannelFeeConfigList feeConfig = null;
        // 过滤 支付类型
        Predicate<ProviderChannelFeeConfigList> isPayType = merchantFeePayConfig -> merchantFeePayConfig.getPayWayDO().getType()  == payType.getCode();
        // 过滤 支付场景
        Predicate<ProviderChannelFeeConfigList> isSceneType = merchantFeeSceneConfig -> merchantFeeSceneConfig.getPayWayDO().getSceneType()  == sceneType.getCode();
        // 过滤并排序
        List<ProviderChannelFeeConfigList> merchantFeeConfigMap = merchantFeeConfigList.stream().filter(isPayType.and(isSceneType)).collect(Collectors.toList());

        Map<String,Object> feeUnitMap = new HashMap<>();

        switch (payType){
            case WECHAT:
            case ALIPAY:
                // 取百分比最高的值
                merchantFeeConfigMap = merchantFeeConfigMap.stream().sorted(Comparator.comparing(merchantFeeSceneConfig -> merchantFeeSceneConfig.getDefaultFeeConfigValue().getRateBase())).collect(Collectors.toList());
                feeConfig = CollUtil.getLast(merchantFeeConfigMap);
                // 默认百分比
                if(feeConfig == null){
                    feeUnitMap.put("rate",38);
                }else{
                    BigDecimal rateBase =  feeConfig.getDefaultFeeConfigValue().getRateBase();
                    if(rateBase == null){
                        rateBase = new BigDecimal(0.38);
                    }
                    //1 百分比 2 固定值 3 百分比+固定值
                    switch (feeConfig.getDefaultFeeConfigValue().getFeeType()){
                        case 1:
                            feeUnitMap.put("rate",rateBase.multiply(new BigDecimal(100)).intValue());
                            break;
                        case 3:
                            feeUnitMap.put("rate",rateBase.multiply(new BigDecimal(100)).intValue());
                            feeUnitMap.put("fixedCharge",feeConfig.getDefaultFeeConfigValue().getFixedRate().multiply(new BigDecimal(1000000)).intValue());
                            break;
                    }
                }
                break;
            case UNION_APY:
                merchantFeeConfigMap = merchantFeeConfigMap.stream().filter(merchantFeeSceneConfig ->  StrUtil.containsIgnoreCase(merchantFeeSceneConfig.getPayWayDO().getCode(),"Union")).collect(Collectors.toList());
                if(CollUtil.isNotEmpty(merchantFeeConfigMap)){
                    feeConfig = merchantFeeConfigMap.get(0);
                }
                // >1000
                if(more1000){
                    // 阶梯费率
                    if(feeConfig == null){
                        // 60表示0.60%
                        feeUnitMap.put("rate",52);
                        // 单位：万分之一分，如60,0000表示每笔交易最高收费0.6元 0不封顶
                        feeUnitMap.put("maxCharge",0);
                    }else{
                        Optional<StepFeeConfig> optional = feeConfig.getStepFeeConfigs().stream().filter(stepFeeConfig -> stepFeeConfig.getEndAmt().intValue() > 1000).findFirst();
                        if(optional.isPresent() && optional.get().getRateBase() != null && optional.get().getRateBase().doubleValue() > 0.51){
                            feeUnitMap.put("rate",optional.get().getRateBase().multiply(new BigDecimal(100)).intValue());
                            feeUnitMap.put("maxCharge",0);
                        }else{
                            feeUnitMap.put("rate",52);
                            feeUnitMap.put("maxCharge",0);
                        }
                    }
                // <1000
                }else{
                    // 阶梯费率
                    if(feeConfig == null){
                        // 60表示0.60%
                        feeUnitMap.put("rate",24);
                        // 单位：万分之一分，如60,0000表示每笔交易最高收费0.6元 0不封顶
                        feeUnitMap.put("maxCharge",20*1000000);
                    }else{

                        Optional<StepFeeConfig> optional = feeConfig.getStepFeeConfigs().stream().filter(stepFeeConfig -> stepFeeConfig.getEndAmt().intValue() <= 1000).findFirst();
                        if(optional.isPresent() && optional.get().getRateBase() != null && optional.get().getRateBase().doubleValue() > 0.23){
                            feeUnitMap.put("rate",optional.get().getRateBase().multiply(new BigDecimal(100)).intValue());
                            feeUnitMap.put("maxCharge",0);
                        }else{
                            feeUnitMap.put("rate",24);
                            feeUnitMap.put("maxCharge",20*1000000);
                        }
                    }
                }

                break;

        }


        return feeUnitMap;
    }

    public CommonResult<LeshuaPayConfig> leshuaPayConfig(ProviderChannelConfigDO providerChannelConfigDO, boolean test) {
        String paramsConfig = providerChannelConfigDO.getParamsConfig();
        if (StringUtils.isEmpty(paramsConfig)) {
            return CommonResult.error(PayResultCode.PAY_CHANNEL_CONFIG_NOT_EXITS);
        }
        // 配置转换
        LeshuaPayConfig leshuaPayConfig = null;
        try {
            leshuaPayConfig = JsonUtils.parseObject(paramsConfig, LeshuaPayConfig.class);
            return CommonResult.success(leshuaPayConfig);
        }
        catch (Exception e) {
            String format = String.format(PayResultCode.PAY_CHANNEL_CONFIG_ERROR.getMsg(), "乐刷");
            return CommonResult.error(PayResultCode.PAY_CHANNEL_CONFIG_NOT_EXITS.getCode(), format);
        }
    }






    public Integer licenseType(String code) {
        if (!StringUtils.hasText(code)) {
            return null;
        }
        // 营业执照类型：
        // 1：营业执照
        // 2：营业执照(多证合一)
        // 3：事业单位法人证书
        // 4：社会团体法人登记证书
        // 5：民办非企业单位登记证书
        // 6：基金会法人登记证书
        // 7：宗教活动场所登记证
        // 8：其他证书/批文/证明
        // 9：执业许可证/执业证
        // 10：基层群众性自治组织特别法人统一社会信用代码证
        // 11：农村集体经济组织登记证
        // 12：业主委员会备案证明

        /**
         * 营业执照（默认）------0
         * 政府部门下发的其他有效证明文件------1
         * 事业单位法人证书------2
         * 民办非企业单位登记证书------3
         * 基金会法人登记证书------4
         * 组织机构代码证------5
         * 统一社会信用代码证书------6
         * 社会团体登记证书(含社会团体法人登记证书、社会服务机构登记证书、工会法人资格证书)------7
         * 执业许可证/执业证(含律师事务所职业许可证、基层法律服务所执业证、司法鉴定许可证)------8
         * 基层群众性自治组织特别法人统一信用代码证------9
         * 农村集体经济组织登记证------10
         * 宗教活动场所登记证------11
         */
        switch (code) {
            case "1":
            case "2":
                return 0;
            case "3":
                return 2;
            case "4":
                return 7;
            case "5":
                return 3;
            case "6":
                return 4;
            case "7":
                return 11;
            case "8":
                return 1;
            case "9":
                return 8;
            case "10":
                return 9;
            case "11":
                return 10;
            default:
                return 0;
        }
    }

    public Integer certType(String code) {
        if (!StringUtils.hasText(code)) {
            return null;
        }
        // 营业执照类型：
        // 1:身份证
        // 2:护照
        // 3:军官证
        // 4:士兵证
        // 5:回乡证
        // 6:户口本
        // 7:外国护照
        // 8:其他
        // 9:暂住证
        // 10:警官证
        // 11:文职干部证
        // 12:港澳台同胞通行证
        // 13:外国人居留证
        // 14:台胞证
        // 15:港澳台居住证
        // 16：营业执照 （只有部分场景才会用到 如 受益人和股东）
        /**
         1：身份证；(默认)
         2：港澳台通行证；
         3：台湾身份证；
         4：香港身份证；
         5：澳门身份证；
         6：护照；
         7：居住证；
         9：其它法定文件
         */
        switch (code) {
            case "1":
                return 1;
            case "2":
                return 6;
            case "12":
                return 2;
            case "9":
                return 7;
            case "8":
                return 9;
            default:
                return 1;
        }
    }

    /**
     * 乐刷进件主体类型
     1: 小微商户
     2: 个体商户
     3: 企业商户
     *
     * 系统主体类型
     * 1：政府机构
     * 2：国营企业
     * 3：私营企业
     * 4：外资企业
     * 5：个体工商户
     * 6：其它组织
     * 7：事业单位
     * 8：业主委员会；
     */
    public Integer companyType(Integer type, MerchantEnum.MERCHANT_TYPE merchantType) {
        // 小微企业
        if(merchantType == MerchantEnum.MERCHANT_TYPE.PERSONAL){
            return 1;
        }
        // 企业
        Integer companyType = null;
        switch (type){
            case 5:
                companyType = 2;
                break;
            case 1:
            case 2:
            case 3:
            case 4:
            case 6:
            case 8:
            case 7:
                companyType = 3;
                break;
        }

        return companyType;
    }


    /**
     * 过去指定场景类型的数据
     * @param sceneList
     * @param senceType
     * @return
     */
    public  MerchantAccessScene getMerchantAccessSceneValue(List<MerchantAccessScene> sceneList, Integer senceType){
        if(CollUtil.isNotEmpty(sceneList)){
            for(MerchantAccessScene accessScene:sceneList){
                if(accessScene.getType() == senceType){
                    return accessScene;
                }
            }

        }
        return null;
    }

    /**
     * 0：对公账户 1：对私法人账户 2：对私非法人账户
     * @param type
     * @return
     */
    public Integer getBankAccountType(Integer type){
        Integer bankAccountType = null;
        if(type == null){
            return bankAccountType;
        }
        switch (type){
            case 0:
                bankAccountType = 2;
                break;
            default:
                bankAccountType = 1;
                break;
        }
        return bankAccountType;
    }

    /**
     * 乐刷上传图片获取merQualUrl
     * @param key  key值 用于错误提示
     * @param filePath  本地路劲/https
     * @param leshuaPayConfig
     * @return
     */
    public String getUploadMerQualUrl(String key,String filePath, LeshuaPayConfig leshuaPayConfig) {

        String errorMsg = "乐刷 Upload 上传文件格式异常 , "+key+ " is null";
        if(StrUtil.isEmpty(filePath)){
            log.error(errorMsg);
            throw new RuntimeException(errorMsg);
        }

        File file = null;
        if(HttpUtil.isHttp(filePath)  || HttpUtil.isHttps(filePath) ){
            // 创建临时文件
            file =  FileUtil.createTempFile("."+ ImageUtils.getFileExtension(filePath),true);
            // 文件流copy到临时文件
            HttpUtil.downloadFile(filePath,file);
        }else{
            file = FileUtil.newFile(filePath);
        }

        if(FileUtil.isEmpty(file)){
            log.error(errorMsg);
            throw new RuntimeException(errorMsg);
        }

        String result = uploadPicApi(file,leshuaPayConfig);
        log.info("乐刷 Upload 上传文件 filePath :{}, 配置 :{}, 返回参数 :{}",filePath, JSONUtil.toJsonStr(leshuaPayConfig),result);
        if(StrUtil.isNotEmpty(result)){
            return result;
        }else{
            throw new RuntimeException("乐刷 Upload 上传文件异常 : "+filePath);
        }
    }


    /**
     * 获取支付方式
     * @param payWayDO
     * @return
     */
    public String getPayWay(PayWayDO payWayDO){
        String payway = null;
        // 支付渠道枚举
        PayEnums.SCENE_PAY_TYPE scenePayType = PayEnums.SCENE_PAY_TYPE.from(payWayDO.getSubType());
        // 支付方式枚举
        PayEnums.PAY_TYPE payType = PayEnums.PAY_TYPE.fromByCode(payWayDO.getType());
        switch (payType){
            case WECHAT:
                payway = "WXZF";
                break;
            case ALIPAY:
                payway = "ZFBZF";
                break;
            case UNION_APY:
                payway = "UPSMZF";
                break;
        }

        return payway;
    }

    /**
     * 获取渠道类型
     * @param payWayDO
     * @return
     */
    public String getPayChannel(PayWayDO payWayDO){
        String  payChannel = null;
        PayEnums.PAY_TYPE payType = PayEnums.PAY_TYPE.fromByCode(payWayDO.getType());
        switch(payType){
            case WECHAT:
                payChannel = "WECHAT";
                break;
            case ALIPAY:
                payChannel = "ALIPAY";
                break;
            case UNION_APY:
                payChannel = "UNIONPAY";
                break;
            case DIGITAL:
                payChannel = "DCEP";
                break;
        }
        return payChannel;
    }


    /**
     * 获取支付场景
     * @param payWayDO
     * @return
     */
    public String getPayScene(PayWayDO payWayDO){
        String scene = null;
        PayEnums.SCENE_TYPE sceneType = PayEnums.SCENE_TYPE.from(payWayDO.getSceneType());
        switch (sceneType){
            case OFFLINE:
                scene = "OFFLINE";
                break;
            case ONLINE:
                scene = "ONLINE";
                break;
        }
        return scene;
    }

    /**
     * 获取乐刷分账明细单号
     * @param ledgerNo     分账接收方编号
     * @param divideDetail 分账详情
     * @param type 取值类型 true:取类型 false:明细单号
     * @return
     */
    public String getDivideDetailNo(String ledgerNo,String divideDetail,boolean type){
        if(StrUtil.isEmpty(divideDetail)){
            return null;
        }
        List<YeePayDivideDetailResp> detailRespList = JSONUtil.toList(divideDetail,YeePayDivideDetailResp.class);
        if(CollUtil.isNotEmpty(detailRespList)){
            for(YeePayDivideDetailResp detailResp:detailRespList){
                if(detailResp.getLedgerNo().equals(ledgerNo)){
                    if(type){
                        return detailResp.getLedgerType();
                    }else{
                        return detailResp.getDivideDetailNo();
                    }

                }
            }
        }
        return null;
    }

    public PayOrderDO queryPayOrder(String orderId){
        return payOrderService.queryPayOrderNoCache(orderId);
    }

    /**
     * 时间戳转DateTime
     * @param timestamp
     * @return
     */
    public long formatTimestamp(long timestamp,boolean minute){
        long second = (timestamp-System.currentTimeMillis())/1000;
        if(minute){
            return second/60;
        }
        return second;
    }





    /**
     * 获取商户号
     * @param leshuaPayConfig
     * @param payType  微信/支付宝
     * @return
     */
    public List<String> getMchId(LeshuaPayConfig leshuaPayConfig,String subMchId,PayEnums.PAY_TYPE payType){
        log.info("乐刷查询商户号 查询参数 subMchId:{} PAY_TYPE:{}", subMchId,payType.getType());
        LeshuaBaseResp response = null;
        List<String> mchIds = new ArrayList<>();
        // 查询微信子商户号
        Map<String,Object> data = new HashMap<>();
        data.put("merchantId",subMchId);
        switch (payType){
            case WECHAT:
                data.put("subMchType",1);
                response = requestPostApi(LeshuaPayConstant.SUBMCH_RUL,JSONUtil.toJsonStr(data),leshuaPayConfig);
                log.info("乐刷查询微信商户号 返回参数:{}", response);
                if(LeshuaPayConstant.OK.equals(response.getRespCode())){
                    LeshuaAccessWechatResp wechatResp = JSONUtil.toBean(response.getData(),LeshuaAccessWechatResp.class);
                    if(CollUtil.isNotEmpty(wechatResp.getWechat())){
                        mchIds = wechatResp.getWechat().stream().filter(wechat -> wechat.getUsable().equals("1")).map(LeshuaAccessWechatDetailResp::getSubMchId).collect(Collectors.toList());
                    }
                }
                break;
            case ALIPAY:
                data.put("subMchType",2);
                response = requestPostApi(LeshuaPayConstant.SUBMCH_RUL,JSONUtil.toJsonStr(data),leshuaPayConfig);
                log.info("乐刷查询支付宝商户号 返回参数:{}", response);
                if(LeshuaPayConstant.OK.equals(response.getRespCode())){
                    LeshuaAccessAliResp aliResp = JSONUtil.toBean(response.getData(), LeshuaAccessAliResp.class);
                    if(CollUtil.isNotEmpty(aliResp.getAlipay())){
                        mchIds = aliResp.getAlipay().stream().filter(wechat -> wechat.getUsable().equals("1")).map(LeshuaAccessAliDetailResp::getSubMchId).collect(Collectors.toList());
                    }
                }
                break;
        }
        log.info("乐刷查询商户号 返回参数 mchIds:{} ", JSONUtil.toJsonStr(mchIds));
        return mchIds;
    }



    /**
     * 获取聚合签名值
     * @param jsonData
     * @param leshuaPayConfig
     * @return
     */
    public static String getSignByLepos(String jsonData, LeshuaPayConfig leshuaPayConfig) {
        String sign = "";
        StringBuffer sb = new StringBuffer("lepos");
        sb.append(leshuaPayConfig.getAccessKey()).append(jsonData);//key每个渠道商不一样
        try {
            String md5 = DigestUtils.md5Hex(sb.toString().getBytes(leshuaPayConfig.getCharset()));
            sign = Base64.encodeBase64String(md5.getBytes(leshuaPayConfig.getCharset()));
        } catch (UnsupportedEncodingException e) {
            log.error("签名异常:{}",e.getMessage());
        }
        return sign;
    }

    /**
     * 回调签名校验
     * @param request
     * @param leshuaPayConfig
     * @return
     * @throws Exception
     */
    public String decrypt(HttpServletRequest request, LeshuaPayConfig leshuaPayConfig,boolean checkSign) throws Exception {
        // 获取响应内容
        String responseText = XmlUtils.getContentFromRequestInputStream(request);
        if (StrUtil.isEmpty(responseText)) {
            return null;
        }
        Map<String,String> respData = XmlUtils.getMapFromXML(responseText);
        String result = JSONUtil.toJsonStr(respData);
        // 获取响应数据签名
        String oldSign = respData.get("sign");
        // 拼接字符串
        String str2Sign = HttpClientHelper.buildParamSign(respData,notifyExcludedSignParams(),leshuaPayConfig.getNotifyKey());
        //获取新签名值
        String newSign = DigestUtils.md5Hex(str2Sign).toUpperCase();
        log.info("MD5签名原始串：{}，签名结果：{}", oldSign, newSign);
        if(checkSign){
            if(!oldSign.equalsIgnoreCase(newSign)){
                log.info("签名校验失败！");
                return null;
            }
        }
        return result;
    }


    public String requestPostApi(String url,Map<String,String> params, LeshuaPayConfig leshuaPayConfig){
        log.info("请求地址:{},请求参数:{} ",url,JSONUtil.toJsonStr(params));
        // 随机字符串
        params.put("nonce_str", IdUtil.fastSimpleUUID());
        // 拼接字符串
        String str2Sign = HttpClientHelper.buildParamSign(params,reqExcludedSignParams(),leshuaPayConfig.getAccessKey());
        //获取签名值
        String signResult = DigestUtils.md5Hex(str2Sign).toUpperCase();
        log.info("MD5签名原始串：{}，签名结果：{}", str2Sign, signResult);
        params.put("sign",signResult);
        String result = httpClientHelper.postForm(url,params,HttpClientHelper.ACCEPT_TYPE_X_WWW);
        return JSONUtil.toJsonStr(XmlUtil.xmlToMap(result));
    }


    /**
     *
     * 请求参数不参与计算签名的参数
     * @return
     */
    protected Set<String> reqExcludedSignParams() {
        Set<String> exludedSignParams = new HashSet<String>(1);
        exludedSignParams.add("sign");
        return exludedSignParams;
    }

    /**
     *
     * 响应结果不参与计算签名的参数
     * @return
     */
    protected Set<String> resExcludedSignParams() {
        Set<String> exludedSignParams = new HashSet<String>(2);
        exludedSignParams.add("sign");
        exludedSignParams.add("resp_code");
        return exludedSignParams;
    }

    /**
     *
     * 响应结果不参与计算签名的参数
     * @return
     */
    public static Set<String> notifyExcludedSignParams() {
        Set<String> exludedSignParams = new HashSet<String>(2);
        exludedSignParams.add("sign");
        exludedSignParams.add("error_code");
        return exludedSignParams;
    }


    /**
     * 元变成分
     * @param amount
     * @param scale
     * @return
     */
    public String yuanToFen(String amount,Integer scale){
        if(!NumberUtil.isNumber(amount)){
            return "0";
        }
        if(scale == null){
            scale = 2;
        }
        BigDecimal result = NumberUtil.mul(amount,"100").setScale(scale, RoundingMode.HALF_UP);
        return result.toString();
    }

    /**
     * 分变成元
     * @param amount
     * @param scale
     * @return
     */
    public String fenToYuan(String amount,Integer scale){
        if(!NumberUtil.isNumber(amount)){
            return "0";
        }
        if(scale == null){
            scale = 2;
        }
        BigDecimal result = NumberUtil.div(amount,"100").setScale(scale, RoundingMode.HALF_UP);
        return result.toString();
    }

    /**
     * post请求
     * @param url
     * @param data
     * @param leshuaPayConfig
     * @return
     */
    public LeshuaBaseResp requestPostApi(String url,String data, LeshuaPayConfig leshuaPayConfig){
        log.info("请求地址:{},请求参数:{} ",url,data);
        //获取签名值
        String sign = getSignByLepos(data,leshuaPayConfig);

        MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
        multipartEntityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
        multipartEntityBuilder.setCharset(Charset.forName(leshuaPayConfig.getCharset()));
        multipartEntityBuilder.addPart("agentId", new StringBody(leshuaPayConfig.getAgentId(), ContentType.APPLICATION_JSON));//代理商编号
        multipartEntityBuilder.addPart("version", new StringBody(leshuaPayConfig.getVersion(), ContentType.APPLICATION_JSON));//版本
        multipartEntityBuilder.addPart("reqSerialNo", new StringBody(IdUtils.getSnowflakeNextIdStr(), ContentType.APPLICATION_JSON));//请求流水号

        multipartEntityBuilder.addPart("data", new StringBody(data, ContentType.APPLICATION_JSON));//数据内容
        multipartEntityBuilder.addPart("sign", new StringBody(sign, ContentType.APPLICATION_JSON));//签名值

        HttpEntity reqEntity = multipartEntityBuilder.build();

        return httpClientHelper.postWithMultipartEntity(url,null,reqEntity,leshuaPayConfig.getCharset());
    }


    public LeshuaBaseResp requestPostApi(String url,String data, LeshuaPayConfig leshuaPayConfig,String reqSerialNo){
        log.info("请求地址:{},请求参数:{} ",url,data);
        //获取签名值
        String sign = getSignByLepos(data,leshuaPayConfig);

        MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
        multipartEntityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
        multipartEntityBuilder.setCharset(Charset.forName(leshuaPayConfig.getCharset()));
        multipartEntityBuilder.addPart("agentId", new StringBody(leshuaPayConfig.getAgentId(), ContentType.APPLICATION_JSON));//代理商编号
        multipartEntityBuilder.addPart("version", new StringBody(leshuaPayConfig.getVersion(), ContentType.APPLICATION_JSON));//版本
        if(StrUtil.isEmpty(reqSerialNo)){
            multipartEntityBuilder.addPart("reqSerialNo", new StringBody(IdUtils.getSnowflakeNextIdStr(), ContentType.APPLICATION_JSON));//请求流水号
        }else{
            multipartEntityBuilder.addPart("reqSerialNo", new StringBody(IdUtils.getSnowflakeNextIdStr(), ContentType.APPLICATION_JSON));//请
        }

        multipartEntityBuilder.addPart("data", new StringBody(data, ContentType.APPLICATION_JSON));//数据内容
        multipartEntityBuilder.addPart("sign", new StringBody(sign, ContentType.APPLICATION_JSON));//签名值

        HttpEntity reqEntity = multipartEntityBuilder.build();

        return httpClientHelper.postWithMultipartEntity(url,null,reqEntity,leshuaPayConfig.getCharset());
    }

    /**
     * 封装请求参数
     * @param data  请求数据
     * @param file
     * @param leshuaPayConfig
     * @return
     */
    private static HttpEntity getHttpEntity(String data,File file,LeshuaPayConfig leshuaPayConfig){
        //获取签名值
        String sign = getSignByLepos(data,leshuaPayConfig);
        MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
        multipartEntityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
        multipartEntityBuilder.setCharset(Charset.forName(leshuaPayConfig.getCharset()));
        multipartEntityBuilder.addPart("agentId", new StringBody(leshuaPayConfig.getAgentId(), ContentType.APPLICATION_JSON));//代理商编号
        multipartEntityBuilder.addPart("version", new StringBody(leshuaPayConfig.getVersion(), ContentType.APPLICATION_JSON));//版本
        multipartEntityBuilder.addPart("reqSerialNo", new StringBody(IdUtils.getSnowflakeNextIdStr(), ContentType.APPLICATION_JSON));//请求流水号
        multipartEntityBuilder.addPart("data", new StringBody(data, ContentType.APPLICATION_JSON));//数据内容
        multipartEntityBuilder.addPart("sign", new StringBody(sign, ContentType.APPLICATION_JSON));//签名值
        // 文件参数
        if(file != null){
            multipartEntityBuilder.addPart("media", new FileBody(file));
        }
        HttpEntity reqEntity = multipartEntityBuilder.build();
        return reqEntity;
    }

    /**
     * 上传图片
     * @param file
     * @param leshuaPayConfig
     * @return
     */
    public static String uploadPicApi(File file,LeshuaPayConfig leshuaPayConfig){
        Map<String,Object> data = new HashMap<>();
        String myMD5 = null;
        try {
            myMD5 = DigestUtils.md5Hex(new FileInputStream(file));
        } catch (IOException e) {
            e.printStackTrace();
        }
        data.put("fileMD5",myMD5);
        LeshuaBaseResp result = httpClientHelper.postWithMultipartEntity(LeshuaPayConstant.PIC_UPLOAD_RUL,null,getHttpEntity(JSONUtil.toJsonStr(data),file,leshuaPayConfig),leshuaPayConfig.getCharset());
        if(result.getRespCode().equals(LeshuaPayConstant.OK)){
            LeshuaPicUploadResp picUploadResp = JSONUtil.toBean(result.getData(),LeshuaPicUploadResp.class);
            return picUploadResp.getPhotoUrl();
        }
        return null;
    }

    public static void main(String[] args) {
        LeshuaPayConfig leshuaPayConfig = new LeshuaPayConfig();
        leshuaPayConfig.setAgentId("3875552");
        leshuaPayConfig.setAccessKey("7FA2939A2301413DB8D36BCA9A605A7F");
        leshuaPayConfig.setNotifyKey("5EF966D9DC744264BFA60E6BBD652C9B");
        //
        // String contenttype = ContentType.MULTIPART_FORM_DATA.getMimeType();
        // System.out.println(contenttype);
        // String img = "E:/cert/gift_8.png";
        // //图片
        // File file = FileUtil.newFile(img);
        // String result = uploadPicApi(file,leshuaPayConfig);
        // System.out.println(result);


        Map<String,String> params = new HashMap<>();
        params.put("service","query_status");
        params.put("merchant_id","111");
        params.put("third_order_id","M11111");

        System.out.println(IdUtils.getSnowflakeNextIdStr());
        System.out.println(IdUtils.getSnowflakeNextIdStr().length());



    }


}
